//
//  main.swift
//  常亮变量
//
//  Created by MyMac on 15/10/8.
//  Copyright (c) 2015年 tongfang. All rights reserved.
//

import Foundation

//print("Hello, World!")
/// 声明时已经决定了变量常亮的类型，后面改动时还是按这个类型编译
let i:Float=1.9999009999999999+0.999+10
//let c=-0.9;
var b:Float
b=0.999
if b==0.999
{

print("true")


}
print(i)
print(b)
var str:String="111"
//print(str)
var strBool:String?//可选值要是一个变量
if (str==strBool) {
    
    print(strBool);
    
}
//强制转换
let ret=integer_t(b)
print(ret)
//UInt32无符号
let unsignedInt:UInt32=UInt32.max
print(unsignedInt)
//布尔值只有true false
let bool=false;


if(bool){

    print(bool);
}else{
    print(bool);

}
//元组("luojie",11,33)
let student:(String,Int,Int,Int)=("luojie",11,33,444)
print("元组%@",student.0,student.3)
print(student.1)
print(student.2)
//_在swift代表通配符
//元组类似一个字典，或者结构体
let (name,age,year,_)=student;
let (conent,num)=("1111",22)
print("name",name)
print(year)
print(age)
let teacher=(name:"niuhui",age:11)
print(teacher.name,teacher.age)


//可选值 Optional 两种状态  1.有值，没有值（nil）
//swift中当方法返回时，有可能有值，也可能没值，这时你用一个可选类型届   Int？表示int的可选类型，可能有一个int值，也可能没有int值（缺失 nil）
//swift中nil与oc中不一样，oc中表示不指向任何对象，而swift中表示值的缺失
//无值
//var optValue:Int?
//有值
var optValue:Int?=9


print(optValue!)//当确定可选值为非nil时，在可选值后加！可以获取到可选值的值，如果为nil，会运行报错




//通过if语句判断可选值是否包含
if (optValue == nil) {

    print(optValue);

}

//可选绑定,通过可选绑定来判断可选值是否包含，将可选绑定bindValue的值赋给tempBind，如果赋值成功就为真，表示可选值有值（非nil）
var bindValue:String?="bangding"
if var tempBind=bindValue{

print(tempBind)

}
//通过if语句判断可选值是否包含，通过可选绑定来解析可选值

//隐式解析可选类型：可以确定这个可选类型一直有值，后面使用时可以不需要再通过if判断和用可选绑定解析
let optBty:Int!=13//只是将类型后的？改为！
print(optBty)//解析值时不需要再加！

//普通可选类型
let usualBty:Int?=15
print(usualBty!)

var c:Character="z"
print(c)

var str1:String="罗杰"
print(count(str1))//字符串长度（元素个数）

let all=String(c)+str1//字符串拼接
print(all)

print("你好\(all)\(b)")//通用拼接\()

//字符串比较，，，可以直接用关系运算符
let compare="hello"
if compare>="ahello"{
print(compare)
print(compare.uppercased())

}

//区间运算
//闭区间运算 （a，，，b）1...3->1,2,3
//半闭区间    （a..<b）1..<3->12
for i in 2...5
{
  print(i)

}

let array=[1,1,1,2,3,4,5]
print(array.count)


let appName="ios"
switch appName{
case  "ios":
print("ios")
    fallthrough//继续往下
case  "anzhuo":
print("anzhuo")
default :
    print("缺失")
}


//函数调用
let funcRet=text2()
print(funcRet)
 //参数命名
let ret3=text3("ios", andValue: "andord", andNumber: 2)
print(ret3)

//返回值可以是多个
var func4=text4()
print(func4.0)


//返回一个函数指针
let func6=text6()//返回一个函数，func6是一个函数
print(func6)



//通过返回的函数再调用这个函数
//let func7=func6(199,"haha")//调用func6这个函数，返回值是Int
let fun7=func6()
print(fun7)




//函数当作参数传递
text8()

//字典
//<String,String>规定了字典键值的类型
var dict:Dictionary <String,String>=["name":"luojie","age":"12","ClassM":"44"];
dict.updateValue("33", forKey: "name")
print(Array(dict.keys))
print(Array(dict.values))//要强转
dict["T"]="hahaah"
print(dict)



// 数组
var arr=["haha",12,44]
arr[0]="jjjj"
print(arr[1])
arr.append(22)
arr.remove(at: 3)
arr.append(["name":"luojie","age":12])
print(arr)

let numbers=[["name":"luojie","age":12]]
//在一个多类型数组中无法单独找到一个字典类型hashable表示乱放进去，但还能找到的，在快速枚举中找不到字典
//for value:Dictionary in arr{
//
//    print(value)
//
//}

//闭包Closure,swift是数据安全的，参数是什么类型就必须传什么类型
func closureMethon(_ closure:(n : Int) ->Bool,a: NSArray){
     for item in a{
        //as类型转换 表示一个变量是一个什么类型   加！表非
        //表示n是一个int类型且不是NSNumber
        var bo=closure(n: Int(item as! NSNumber))
        if (bo){
        
        print("符合")
        }else{
        
        print("不符合")
        }
    
    
    }


}

var numb=[12,33,44,55,66,33]
closureMethon({(c: Int) ->Bool in
    
    return c>=40;
    
}, numb)








let closure={(n:Int) ->Bool in
    
    print("hahaha")
    
    return n>=30
}

let v=closure(10)
print(v)


//swift是数据安全的，严格控制数据类型
closureMethonTransmit({ (s,aArr) -> Bool in
    for i in aArr {
        if  Int(i as! NSNumber )<=s {
        
        print("符合")
    
        }else{
        print("不符合")
        }
    }
    
   return true
}, "hahaha")




closureAndMethonDifferent({ (name, age) -> String in
    return "我是方法传递name:\(name) and ade:\(age)"
}, {
    //这里没有写(cName, cAge) -> String in
    //$0表示cName  $1表示cAge
    return  "我是闭包传递cName:\($0) and ade:\($1)"
})




func methon (_ name:String ,age:Int) ->String
{

return "我是方法传递name:\(name) and ade:\(age)"

}
//方法传递和闭包的区别
//在swift中可以直接传递一个方法(类似oc中的Selector)，所以此时闭包和方法在结果上是没区别的
closureAndMethonDifferent(methon, { (cName, cAge) -> String in
return  "我是闭包传递cName:\(cName) and ade:\(cAge)"

})


//枚举
enum Color {
  case green
  case red
  case black
}
var c1=Color.black
print(c1)
if c1==Color.black {
//枚举值无法直接打印出来,但可以直接比较
print(c1)

}

enum Student {

 case name ,age,year

}
print(Student.age.hashValue)
//类似于c 每个值代表一个整形
enum Teacher :Int {
  case classes = 2//注意＝左右的空格
  case year
  case size
}
print(Teacher.classes.rawValue)

var t:Teacher=Teacher.classes
print(t.rawValue)

var t1=Teacher(rawValue: 2)//强转
print(t1)

//值类型被赋值，传递都是他的拷贝
var param1="haha"
var param2 = "mimi"

var param3=param1
param3="lili"
//param1没变 param3变了，值类型的传递都是复制，结构体，枚举也都是值类型
print("1:\(param1) 3:\(param3)")


struct size {
    var x = 0
    var y = 0
    //结构体可以带构造函数（对象初始化时调用）
    //不同的写的方式对应不同的调用方式
    init(){
    
    print("构造1")
    
    }
    init (x:Int,y:Int) {
    self.x=x
    self.y=y
    print("构造2")
    }
   //结构体可以把函数当作成员变量
    //结构体内部是不能修改里面的变量的，要想修改，必须加mutating修饰
    //结构体，枚举都是值类型，而类是引用类型，在值类型的“实例”方法中是默认不能修改这个值类型的属性的，要想修改，必须加mutating关键字
 mutating  func text (_ name:String , age:Int) {
        x++
        y++
    print("\(name) and \(age)")
    }
   
}
var s=size(x: 3,y: 4)
print(s.x)

var s1=size()
s1.x=19
print(s1.x)
s.text("sss", age: 77)


//类
//类方法的定义和调用与结构体的定义和调用类似
//初始化方式也一样
//lazy表示懒加载
class Person  {
    var name:String?
    lazy var age:Int=10
    //一般我们都会写两种构造函数，以应对不同的初始化方式,或者不写，系统内部自己调用
     init(){
    
    print("\(name) and \(age)")
    
    }
    //计算型属性，里面自己实现的set和get方法
    //必须实现get方法，可以不用实现set方法，此时该属性是只读的，不能赋值
    //get方法必须返回一个值，不能用oc中的 _属性名 语法
   var  ager : Int {
    get {
    print("get")
    //怎么返回这个属性自己
    return 20
    }
    //set方法 格式 set （属性名）｛｝,属性名可以省略，默认newValue
    set {
    print("set:\(newValue)")
    }
    }
    init (name:String ,age:Int){
    self.name=name
    self.age=age
    print("\(name) and \(age)")
    }
    func tempFunc (){
    //类中，，，方法可以直接引用里面的变量
    self.age++
    }
   //类方法前面加class
    class func add (){
    
    print("类方法调用")
    
    }
    //析够函数
   deinit{
    print("析够函数dealloc")
    }
   }
var p=Person(name:"luojie" ,age:24)
print(p.name)
Person.add()
var q=Person()// 创造一个对象
Person.add()
q.age=19
q.tempFunc()
print(q.age)
p.ager=11
print(q.ager)

//@objc表示兼容oc协议
//swift中的协议类似于一个类，这个类里面定义了一些方法和属性，当类，结构体或枚举遵循了／继承了这个协议，那就必须得实现这个协议的标准
//@objc表示可以让oc调用
@objc protocol testProtocol :NSObjectProtocol{
    //optional表示这个协议可选
  optional  var x:Int {set get}
    var y:Int {set get}

    func text1(_ t1:Int) ->Int
  optional  func text2 (_ t2:Int) ->Int


}

class ClassT : NSObject,testProtocol {
    func text1(_ t1: Int) -> Int {
        return  t1
    }
    //var x=22
    var y=77
    
    func text2(_ t2: Int) -> Int {
        return t2
    }
}

let c4=ClassT()
print(c4.text1(11))
print(c4.text2(7) )
//print(c4.x)
print(c4.y)

let c5=c4 as testProtocol//将一个对象强转成协议
//因为text2是可选的，不知道有没有实现，所以调用的时候不知道有没有值，所以用?表示可选
print(c5.text2?(99))












